#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <QDebug>
#include <QFileDialog>
#include <QSettings>
#include <QMessageBox>
#include <QArrayData>
#include <QFile>
#include <QDir>
#include <QProcess>

#include "aboutdialog.h"
#include "helpdialog.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    curExePath = QApplication::applicationDirPath();

    readSettings();

    outPutModel = new QFileSystemModel;
    inPutModel = new QFileSystemModel;

    initUi();

    QDir *photo = new QDir;
    bool exist;
    exist = photo->exists(QString(curExePath + "/RPK/run.rpk"));
    if(!exist){
        photo->mkdir(QString(curExePath + "/RPK"));
        QMessageBox::warning(this,"严重错误",QString("请在rpk文件夹中放入游戏程序！"),QMessageBox::Ok);
    }
}

void MainWindow::closeEvent(QCloseEvent *event)
{
    MainWindow::writeSettings();
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::initUi()
{
    ui->fileComboBox->clear();
    ui->fileComboBox->addItem(inPutPath);

    ui->outPutPathComboBox->clear();
    ui->outPutPathComboBox->addItem(outPutPath);

    ui->classNum->setText(QString("%1").arg(txtInf.classNum));
    ui->groupNum->setText(QString("%1").arg(txtInf.groupNum));
    ui->modelNum->setText(QString("%1").arg(txtInf.modelNum));
    ui->gameStartCode->setText(QString("%1").arg(txtInf.runOid));
    ui->dataWriteLoc->setValue(dataWriteLoc);

    outPutModel->setRootPath(outPutPath);
    outPutModel->setNameFilters({"*.data"});
    ui->treeView->setModel(outPutModel);
    ui->treeView->setRootIndex(outPutModel->index(outPutPath));

    inPutModel->setRootPath(inPutPath);
    inPutModel->setNameFilters({"*.txt"});
    inPutModel->setFilter(QDir::Files | QDir::NoSymLinks);
    ui->listView->setModel(inPutModel);
    ui->listView->setRootIndex(inPutModel->index(inPutPath));

    ui->label_8->setVisible(false);
    ui->dataWriteLoc->setVisible(false);
    ui->label_6->setVisible(false);
    ui->modelNum->setVisible(false);
}

void MainWindow::on_setInputPathButton_clicked()
{
    inPutPath = QFileDialog::getExistingDirectory(this,
                                                  tr("输入文件路径"),
                                                  inPutPath);
    if(inPutPath.isEmpty()){
        QMessageBox::warning(this,tr("警告"),"请选择有效的输入文件路径！");
    }
    qDebug() << inPutPath;

    QDir dir(inPutPath);
    QStringList filters;
          filters << "*.txt";
          dir.setNameFilters(filters);
    dir.setFilter(QDir::Files | QDir::NoSymLinks);
    dir.setSorting(QDir::Name);
    QFileInfoList list = dir.entryInfoList();

    for (int i = 0; i < list.size(); ++i) {
      QFileInfo fileInfo = list.at(i);
      qDebug() << qPrintable(QString("%1").arg(fileInfo.fileName()));
    }

    initUi();
}

void MainWindow::on_setOutputPathButton_clicked()
{
    outPutPath = QFileDialog::getExistingDirectory(this,
                                      tr("文件生成路径"),
                                      outPutPath);
    if(outPutPath.isEmpty()){
        QMessageBox::warning(this,tr("警告"),"请选择有效的文件生成路径！");
    }
    qDebug() << outPutPath;

    initUi();
}

void MainWindow::on_makeButton_clicked()
{
    QString file = ui->listView->currentIndex().data().toString();
    QStringList fileInf;

    if(file.isNull()){
        QMessageBox msg;
        msg.setWindowTitle("注意");
        msg.setText("请选择一个文件！");
        msg.exec();
        return;
    }
    else {
        fileInf = file.split(QRegExp(QRegExp("[@.]")),QString::SkipEmptyParts);
        if(fileInf.length() < 3){
            QMessageBox msg;
            msg.setWindowTitle("注意");
            msg.setText("请检查文件名称是否正确！");
            msg.exec();
            return;
        }
    }

    QString displayString;
    QList<int> content;
    QFile txtfile(inPutPath+"/"+file);
    if(!txtfile.open(QIODevice::ReadOnly | QIODevice::Text))
    {
        qDebug()<<"Can't open the file!"<<endl;
    }
    while(!txtfile.atEnd())
    {
        QByteArray line = txtfile.readLine();
        qDebug() << line;
        content.append(content2Int(line));
    }
    txtfile.close();

    if(ui->checkBox->isChecked()){
        txtInf.runOid = ui->gameStartCode->text().toInt();
    }
    createGame(txtInf,content);
}

void MainWindow::writeSettings()
{
    QString wstrFilePath = qApp->applicationDirPath() + "/config.ini" ;

    QSettings *settings = new QSettings(wstrFilePath,QSettings::IniFormat);
    settings->beginGroup("mainWindow");
    settings->setValue("size", size());
    settings->setValue("state", saveState());
    settings->endGroup();

    settings->beginGroup("Path");
    settings->setValue("inputFile", inPutPath);
    settings->setValue("outFilePath", outPutPath);
    settings->endGroup();

    settings->beginGroup("param");
    settings->setValue("dataWriteLoc", dataWriteLoc);
    settings->endGroup();

}

void MainWindow::readSettings()
{
    QString wstrFilePath = qApp->applicationDirPath() + "/config.ini" ;

    QSettings *settings = new QSettings(wstrFilePath,QSettings::IniFormat);
    settings->beginGroup("mainWindow");
    resize(settings->value("size").toSize());
    restoreState(settings->value("state").toByteArray());
    settings->endGroup();

    settings->beginGroup("Path");
    inPutPath = settings->value("inputFile").toString();
    outPutPath = settings->value("outFilePath").toString();
    settings->endGroup();

    settings->beginGroup("param");
    dataWriteLoc = settings->value("dataWriteLoc").toInt();
    settings->endGroup();
}

void MainWindow::on_about_triggered()
{
    aboutDialog about;
    about.setWindowTitle("关于");
    about.setFixedSize(321,369);
    about.exec();
}

void MainWindow::on_help_triggered()
{
    helpDialog help;
    help.setWindowTitle("帮助");
    help.exec();
}

int MainWindow::produceRunOid(txtInf_t txtInf){

    int ret = 13000 + (txtInf.classNum-1)*18 + (txtInf.groupNum-1)*2 + 1;
    return ret;
}

int MainWindow::content2Int(QByteArray value){
    int ret = 0;
    int end = value.length()-1;

    // 数字判断
    if((0x30 & value[end])==0x30){
        end = end;
    }
    else {
        end = end-1;
    }

    for(int i=0;i<=end;i++){
        ret = ret*10 + (value[i]-0x30);
    }
    return ret;
}

void MainWindow::createGame(txtInf_t txtInf,QList<int> content){
    QByteArray data;
    for(int i=0;i<dataWriteLoc;i++){
        data.append((quint8)(0));
        data.append((quint8)(0));
        data.append((quint8)(0));
        data.append((quint8)(0));
    }
    for(int i=0;i<content.length();i++){
        data.append((quint8)(content[i]));
        data.append((quint8)(content[i]>>8));
        data.append((quint8)(content[i]>>16));
        data.append((quint8)(content[i]>>24));
    }
    for(int i=0;i<32-dataWriteLoc-content.length();i++){
        data.append((quint8)(0));
        data.append((quint8)(0));
        data.append((quint8)(0));
        data.append((quint8)(0));
    }

    // 创建GAME文件夹
    QDir qd;
    preOutPutPath = outPutPath;
    qd.setCurrent(outPutPath);
    qd.mkdir("GAME");
    outPutPath+="/GAME";

    // 创建子文件夹
    qd.setCurrent(outPutPath);
    qd.mkdir(QString("game-%1").arg(txtInf.runOid));
    outPutPath+="/"+QString("game-%1").arg(txtInf.runOid);

    // rpk 游戏文件放入
    if(!QFile::copy(curExePath+"/RPK/run.rpk", outPutPath + "/run.rpk")){
        QMessageBox::warning(this,"严重错误",QString("游戏生成失败，请在rpk文件夹中放入游戏程序！"),QMessageBox::Ok);
    }

    // 子文件夹中写入数据
    qd.setCurrent(outPutPath);

    // 写入数据
    writeHex(outPutPath,data);

    // 恢复到最初路径
    qd.setCurrent(preOutPutPath);
    outPutPath = preOutPutPath;

    QMessageBox msg;
    msg.setWindowTitle("完成");
    msg.setText("游戏生成完成！");
    msg.exec();
    return;
}

void MainWindow::writeHex(QString filePath,QByteArray data)
{
    QFile fi(filePath+"/game.data");
    fi.open(QIODevice::WriteOnly);
    QDataStream out(&fi);
    foreach (quint8 d, data) {
        out << d;
    }
    fi.close();
}

void MainWindow::on_listView_clicked(const QModelIndex &index)
{
    QString file = index.data().toString();
    QStringList fileInf;
    qDebug() << file;

    if(file.isNull()){
        QMessageBox msg;
        msg.setWindowTitle("注意");
        msg.setText("请选择一个文件！");
        msg.exec();
        return;
    }
    // 改为 班级@组@模板.txt 和 班级@组.txt 两种都支持
    fileInf = file.split(QRegExp(QRegExp("[@.]")),QString::SkipEmptyParts);
    if(fileInf.length() < 3){
        QMessageBox msg;
        msg.setWindowTitle("注意");
        msg.setText("请检查文件名称是否正确！");
        msg.exec();
        return;
    }

    qDebug() << fileInf;
    txtInf.classNum = fileInf[0].toInt();
    txtInf.groupNum = fileInf[1].toInt();
    //txtInf.modelNum = fileInf[2].toInt();
    txtInf.runOid = produceRunOid(txtInf);

    initUi();
}

void MainWindow::on_openButton_clicked()
{
    QProcess process;
    process.start(QString("explorer /select, %1").arg(QDir::toNativeSeparators(outPutPath+"/GAME")));
    //process.waitForFinished();
}

void MainWindow::on_dataWriteLoc_valueChanged(int arg1)
{
    dataWriteLoc = arg1;
}

void MainWindow::on_checkBox_clicked(){
    QCheckBox *cb = (QCheckBox*)(this->sender());
    if(cb->isChecked()){
        ui->gameStartCode->setReadOnly(false) ;
    }else {
        ui->gameStartCode->setReadOnly(true);
    }
}

// =========================NO_GUI==========================
void MainWindow::make(){
    QString displayString;
    QList<int> content;

    QFileInfo fileInfo;
    QDir dir(curExePath);
    dir.setNameFilters({"*.txt"});
    dir.setFilter(QDir::Files | QDir::NoSymLinks);
    dir.setSorting(QDir::Time);
    QFileInfoList list = dir.entryInfoList();
    if(list.size()==0){
        QMessageBox::warning(this,"警告","当前路径下没发现文本文件!");
        return;
    }
    fileInfo = list.at(0);
    qDebug() << fileInfo.fileName();

    //
    QFile txtfile(curExePath+"/" + fileInfo.fileName());
    if(!txtfile.open(QIODevice::ReadOnly | QIODevice::Text)){
        qDebug()<<"Can't open the file!"<<endl;
    }
    while(!txtfile.atEnd()){
        QByteArray line = txtfile.readLine();
        qDebug() << line;
        content.append(content2Int(line));
    }
    txtfile.close();

    QByteArray data;
    dataWriteLoc = 2;
    for(int i=0;i<dataWriteLoc;i++){
        data.append((quint8)(0));
        data.append((quint8)(0));
        data.append((quint8)(0));
        data.append((quint8)(0));
    }
    for(int i=0;i<content.length();i++){
        data.append((quint8)(content[i]));
        data.append((quint8)(content[i]>>8));
        data.append((quint8)(content[i]>>16));
        data.append((quint8)(content[i]>>24));
    }
    for(int i=0;i<32-dataWriteLoc-content.length();i++){
        data.append((quint8)(0));
        data.append((quint8)(0));
        data.append((quint8)(0));
        data.append((quint8)(0));
    }

    // 创建GAME文件夹
    QDir qd;
    outPutPath = curExePath;
    preOutPutPath = outPutPath;

    // 创建子文件夹
    qd.setCurrent(outPutPath);
    qd.mkdir(QString("game-%1").arg(fileInfo.baseName()));
    outPutPath+="/"+QString("game-%1").arg(fileInfo.baseName());

    // rpk 游戏文件放入
    if(!QFile::copy(curExePath+"/RPK/run.rpk", outPutPath + "/run.rpk")){
        QMessageBox::warning(this,"严重错误",QString("游戏生成失败，文件已存在！"),QMessageBox::Ok);
        return;
    }

    // 子文件夹中写入数据
    qd.setCurrent(outPutPath);

    // 写入数据
    QFile fi(outPutPath+"/game.data");
    fi.open(QIODevice::WriteOnly);
    QDataStream out(&fi);
    foreach (quint8 d, data) {
        out << d;
    }
    fi.close();

    // 恢复到最初路径
    qd.setCurrent(preOutPutPath);
    outPutPath = preOutPutPath;

    QMessageBox msg;
    msg.setWindowTitle("完成");
    msg.setText("游戏生成完成！");
    msg.exec();
    return;
}


